我們在昨天介紹了Recursion,並比較了左遞迴與右遞迴的差別。
今天,我們將實際將recusion運用在parser中,來看看是否能夠達成我們預想的規則匹配。
請實作出一個簡易的計算機,能夠對多個正整數做運算(加與減其中之一),並回傳結果。
4 + 7 + 6 - 5 =
Result: 12
%{
#include "main.h"
#include "yacc.tab.h"
%}
posint ([0-9]+)
blank_chars ([ \f\r\t\v]+)
expressions ([-+])
%%
{posint} { yylval = atoi(yytext); return NUMBER; }
{expressions} { return yytext[0]; }
{blank_chars} { ; }
"=" { return yytext[0]; }
\n { ; }
%%
int yywrap(void) {
return 1;
}
%{
#include "main.h"
void yyerror(const char *s);
extern int yylex();
extern int yyparse();
%}
%token NUMBER
%%
func:
expr '=' { printf("Result: %d\n", $1); }
;
expr:
NUMBER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
;
%%
void yyerror(const char *s) {
cerr << s << endl;
}
#ifndef MAIN_H
#define MAIN_H
#include <iostream>
#include <stdio.h>
using namespace std;
#define YYSTYPE int
#endif
#include "main.h"
#include "yacc.tab.h"
extern int yyparse(void);
extern FILE* yyin;
int main()
{
const char* sFile = "file.txt";
FILE* fp = fopen(sFile, "r");
if (fp == NULL) {
printf("cannot open %s\n", sFile);
return -1;
}
yyin = fp;
yyparse();
fclose(fp);
return 0;
}
4 + 7 + 6 - 5 =
Result: 12
今天我們將recusion的語法實際應用在簡易計算機的例子中。
然而,在編譯時卻出現了警告訊息。
yacc.y: conflicts: 4 shift/reduce
我們明天要來好好研究一下,到底發生了甚麼事?